/**
 * form表单常用的控件组合
 * 
 * @method setValues 设置表单的值，只会设置在formList上存在的数据
 * @method resetValues 重置表单的值
 * @method getData 获取表单的值（不校验）
 * @method getValues 获取表单的值（校验）
 * @method validateValues 校验某个或全部的值
 * 
 */

import React, { useEffect, useImperativeHandle, useState, useRef } from 'react';
import styles from './index.module.less';
import useForm from 'rc-form-hooks';
import classnames from 'classnames';
import { Props, FormListItem } from './interface';
import { GenerateUUID } from '@/utils';
import { clearRouteBlocker, onFormGroupChange } from './route-blocker';
import { InputItem, Picker, List, TextareaItem, Toast } from 'antd-mobile-v2';
import ImagePicker from '@/components/image-picker';
import FilePicker from '@/components/file-picker';
import TreeSelecter from '@/components/tree-selecter';
import DatePicker from '@/components/date-picker';
import { RadioSelect } from '../radio-select';
import { CheckboxSelect } from '@/plugins/form/form-components/checkbox-select/view';

// 需要增加组件类型时在下面拓展
const typeMap = {
  text: 'text',
  title: 'title',
  detailTitle: 'detailTitle',
  input: 'input',
  picker: 'picker',
  textArea: 'textArea',
  datePicker: 'datePicker',
  imagePicker: 'imagePicker',
  treeSelecter: 'treeSelecter',
  filePicker: 'filePicker',
  radioSelect: 'radioSelect',
  checkboxSelect: 'checkboxSelect'
};

const FormGroup: React.FC<Props> = React.forwardRef((props, ref) => {
  const { formList = [] } = props;
  const { validateFields, setFieldsValue, getFieldsValue, resetFields, getFieldDecorator, isFieldsTouched } = useForm();
  const [uuid] = useState(GenerateUUID());
  let moneyInputTimer = useRef<any>().current;

  // 表单是否手动修改过
  if (isFieldsTouched(formList.map((item) => item.valueKey))) {
    onFormGroupChange({ routeBlock: props.routeBlock, uuid });
  }

  useEffect(() => {
    return () => {
      clearRouteBlocker(uuid); // 卸载则清除当前污染状态
    };
  }, []);

  // 设置值
  const setValues = (data = {}) => {
    const dataObj = {};
    formList.forEach((item) => { //只设置在formList的数据，否则antd会报不能设置不存在的字段值的warning，
      if (Object.keys(data).indexOf(item.valueKey) > -1) {
        // picker 类型处理
        if (item.type === typeMap.picker) {
          const value = Array.isArray(data[item.valueKey]) ? data[item.valueKey] : [data[item.valueKey]];
          dataObj[item.valueKey] = value;
          return;
        }
        // money 类型 input 处理
        if (item.cellProps?.type === 'money') {
          const value = typeof data[item.valueKey] === 'number' ? data[item.valueKey].toString() : data[item.valueKey];
          dataObj[item.valueKey] = value;
          return;
        }
        dataObj[item.valueKey] = data[item.valueKey];
      }
    });
    setFieldsValue({ ...dataObj });
  };

  // 重置值
  const resetValues = (arg?: any) => {
    resetFields(arg);
  };

  // 校验某个或全部的值
  const validateValues = (arg: any) => {
    return validateFields(arg);
  };

  // 获取数据（不校验）fieldList: [fieldNames: string[]] 也可指定获取哪些字段的值
  const getData = (fieldList?: any[]) => {
    return getFieldsValue(fieldList);
  };

  // 获取数据（校验），返回 Promise 对象
  const getValues = () => {
    return validateFields().then((res: any) => {
      return res;
    }).catch((err: any) => {
      Toast.fail(err.message);
      return Promise.reject(err);
    });
  };

  const getFormItem = (itemData: FormListItem) => {
    switch (itemData.type) {
      case typeMap.text:
        return <List.Item key={itemData.valueKey} className={styles['text-item']} extra={itemData.content || '无'}>{itemData.label}</List.Item>;
      case typeMap.title:
        return <p key={itemData.valueKey} className={styles['form-title']}>{itemData.label}</p>;
      case typeMap.detailTitle:
        return <p key={itemData.valueKey} className={styles['form-detail-title']}>{itemData.label}</p>;
      case typeMap.input:
        if (itemData.cellProps?.type === 'money') {
          // 'money' 类型 input 失焦后隐藏虚拟键盘
          itemData.cellProps.onBlur = () => {
            const keybordDom = document.getElementById('am-number-keyboard-container');
            if (moneyInputTimer) return;
            keybordDom && (keybordDom.style.display = 'none');
          };
          itemData.cellProps.onFocus = () => {
            const keybordDom = document.getElementById('am-number-keyboard-container');
            keybordDom && (keybordDom.style.display = 'block');
            // 防止触发 focus 后立即触发一次 blur
            clearTimeout(moneyInputTimer);
            moneyInputTimer = setTimeout(() => {
              moneyInputTimer = null;
            }, 200);
          };
        }
        return getFieldDecorator(itemData.valueKey, { ...itemData.options })(
          <InputItem
            key={itemData.valueKey}
            className={classnames(styles['input-item'], 'ignore-ratio-border-bottom-left-15')}
            placeholder="请输入"
            {...itemData.cellProps}
          >
            {itemData.label}
          </InputItem>
        );
      case typeMap.picker:
        return getFieldDecorator(itemData.valueKey, { ...itemData.options })(
          <Picker
            key={itemData.valueKey}
            cols={1}
            data={itemData.pickerOptions || []}
            format={(labels) => {
              return labels?.length ? labels.join(',') : getData()[itemData.valueKey]?.join(',');
            }}
            extra={itemData.placeholder}
            {...itemData.cellProps}
          >
            <List.Item
              className={classnames(styles['picker-item'], 'ignore-ratio-border-bottom-left-15', getData()[itemData.valueKey]?.length ? styles['active'] : styles['holder'])}
              arrow="horizontal"
            >
              {itemData.label}
            </List.Item>
          </Picker>
        );
      case typeMap.textArea:
        return getFieldDecorator(itemData.valueKey, { ...itemData.options })(
          <TextareaItem
            key={itemData.valueKey}
            className={styles['textarea-item']}
            title={itemData.label}
            rows={4}
            placeholder="请输入"
            {...itemData.cellProps}
          >
          </TextareaItem>
        );
      case typeMap.datePicker:
        return (
          getFieldDecorator(itemData.valueKey, { ...itemData.options })(
            <DatePicker
              key={itemData.valueKey}
              name={itemData.label}
              {...itemData.cellProps}
              getData={getData}
              setValues={setValues}
            >
            </DatePicker>
          )

        );
      case typeMap.imagePicker:
        return (
          <List.Item key={itemData.valueKey}>
            {getFieldDecorator(itemData.valueKey, { ...itemData.options })(
              <ImagePicker
                {...itemData}
              />
            )}
          </List.Item>
        );
      case typeMap.filePicker:
        return (
          <List.Item key={itemData.valueKey} className={itemData.cellProps.renderMode === 'detail' ? styles.detailMode : ''}>
            {getFieldDecorator(itemData.valueKey, { ...itemData.options })(
              // <ImagePicker
              //   {...itemData}
              // />
              <FilePicker
                formData={props.formData}
                {...itemData.cellProps}
                {...itemData}
              />
            )}
          </List.Item>
        );
      case typeMap.treeSelecter:
        return (
          <React.Fragment key={itemData.valueKey}>
            {
              getFieldDecorator(itemData.valueKey, { ...itemData.options })(
                <TreeSelecter
                  {...itemData}
                  setValues={setValues}
                />
              )
            }
          </React.Fragment>
        );
      case typeMap.radioSelect:
        return (
          <React.Fragment key={itemData.valueKey}>
            {
              getFieldDecorator(itemData.valueKey, { ...itemData.options })(
                <RadioSelect
                  options={itemData?.pickerOptions || []}
                  name={itemData?.label}
                  {...itemData.cellProps}
                />
              )
            }
          </React.Fragment>
        );
      case typeMap.checkboxSelect:
        return (
          <React.Fragment key={itemData.valueKey}>
            {
              getFieldDecorator(itemData.valueKey, { ...itemData.options })(
                <CheckboxSelect
                  code={itemData.valueKey}
                  options={itemData?.pickerOptions || []}
                  name={itemData?.label}
                  {...itemData.cellProps}
                />
              )
            }
          </React.Fragment>
        );
      default:
        return '';
    }
  };

  // 对外调用方法在此导出
  useImperativeHandle(ref, () => ({
    setValues,
    resetValues,
    getValues,
    validateValues,
    getData
  }));

  return (
    <div className={styles.formGroup}>
      <form>
        {
          formList.map((item: FormListItem) => {
            return getFormItem(item);
          })
        }
      </form>
    </div>
  );
});

export default FormGroup;

export {
  Props,
  FormListItem
};